<?php
namespace App\Http\Controllers\ApiUser;

use App\Service\Member\PayService;
use Illuminate\Http\Request;

class PayWxController extends BaseController
{
    //微信支付

    //必须的参数
    protected $app_id = 'wx684d8a09d6ea29fd'; //小程序ID
    protected $mch_id = '1698837235'; //商户号
    protected $key = '4f27cb9de7bfa26859900bc6076c1824'; //秘钥
    protected $notify_url = ''; //通知接口

    public function __construct(PayService $service)
    {
        $this->db = $service;
        $this->notify_url = env('DOMAIN') . '/api/user/pay/wx/notice';
    }

    //测试下单
    public function test()
    {
        $nonce = toOrder();
        $orderno = toOrder();
        $userIp = $this->getUserIp();
        $amount = 1;
        $openid = 'opXLs6zDuFa4dMEmHzonWAHS0p34';
        $type_name = 'test order';
        //构建签名
        $signs = [
            'appid' => $this->app_id,
            'mch_id' => $this->mch_id,
            'nonce_str' => $nonce,
            'body' => $type_name,
            'notify_url' => $this->notify_url,
            'out_trade_no' => $orderno,
            'spbill_create_ip' => $userIp,
            'total_fee' => $amount,
            'trade_type' => 'JSAPI',
            'sign_type' => 'MD5',
            'openid' => $openid,
        ];
        ksort($signs);
        $string = '';
        foreach ($signs as $k => $v) {
            if ($v) {
                $string .= $k . '=' . $v . '&';
            }
        }
        $string .= 'key=' . $this->key;
        echo '<pre>';
//        var_dump($string); echo '<br>string</br>';
        $signStr = strtoupper(md5($string));
//        var_dump($signStr); echo '<br>signStr</br>';
        //构建请求参数
        $param = '';
        $param .= '<xml>';
        $param .= '<appid>' . $this->app_id . '</appid>';
        $param .= '<body>' . $type_name . '</body>';
        $param .= '<mch_id>' . $this->mch_id . '</mch_id>';
        $param .= '<nonce_str>' . $nonce . '</nonce_str>';
        $param .= '<notify_url>' . $this->notify_url . '</notify_url>';
        $param .= '<out_trade_no>' . $orderno . '</out_trade_no>';
        $param .= '<spbill_create_ip>' . $userIp . '</spbill_create_ip>';
        $param .= '<total_fee>' . $amount . '</total_fee>';
        $param .= '<trade_type>JSAPI</trade_type>';
        $param .= '<openid>' . $openid . '</openid>';
        $param .= '<sign_type>MD5</sign_type>';
        $param .= '<sign>' . $signStr . '</sign>';
        $param .= '</xml>';
        $httpUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
//        var_dump($param); echo '<br>xml</br>';
        $res = $this->toCurl($httpUrl, $param);
        return $this->toJson(0, '', $res);
    }

    /**
     * 统一下单
     * https://api.mch.weixin.qq.com/pay/unifiedorder
     * type业务类型：
            1患者咨询医生开启对话uds_patient，
            2患者查看医生帖子tieba_pay，
            3患者发布代办预约订单gc_daiban，
            4患者发布小区医护预约订单gc_yihu，
            5患者发布陪诊预约订单gc_peizhen，
            6药品订单drug_order，
     */
    public function pay(Request $request)
    {
        $token = $request->post('token', '');
        $yw_type = $request->post('yw_type', 0);
        $yw_id = $request->post('yw_id', 0);
        $uOne = $this->db->userByToken($token);
        if(isset($uOne['code']) && $uOne['code']<0)
            return $this->toJson(-2, $uOne['msg']);
        if($uOne)
        if (!in_array($yw_type, [1, 2, 3, 4, 5, 6])) {
            return $this->toJson(-2, '类型错误');
        }
        if (empty($uOne)) {
            return $this->toJson(-2, '没有登录');
        }
        $orderOne = $this->db->wxPayAdd($yw_type, $yw_id, $uOne['id'],1);
        if ($orderOne['code'] < 0) {
            return $this->toJson(-2, $orderOne['msg']);
        }
        $openid = $uOne['openid'];
        $nonce = time();
        $userIp = $this->getUserIp();
        $logid  = $orderOne['data']['payid'];
        $orderno  = $orderOne['data']['orderno'];
        $amount  = $orderOne['data']['price'];
        $type_name = $orderOne['data']['tname'];
        //构建签名
        $signs = [
            'appid' => $this->app_id,
            'mch_id' => $this->mch_id,
            'nonce_str' => $nonce,
            'body' => $type_name,
            'notify_url' => $this->notify_url,
            'out_trade_no' => $orderno,
            'spbill_create_ip' => $userIp,
            'total_fee' => $amount,
            'trade_type' => 'JSAPI',
            'sign_type' => 'MD5',
            'openid' => $openid,
        ];
        ksort($signs);
        $string = '';
        foreach ($signs as $k => $v) {
            if ($v) {
                $string .= $k . '=' . $v . '&';
            }
        }
        $string .= 'key=' . $this->key;
        $this->db->wxPayModify($logid, ['to_sign' => $string]); //支付log
        $signStr = strtoupper(md5($string));
        //构建请求参数
        $param = '';
        $param .= '<xml>';
        $param .= '<appid>' . $this->app_id . '</appid>';
        $param .= '<body>' . $type_name . '</body>';
        $param .= '<mch_id>' . $this->mch_id . '</mch_id>';
        $param .= '<nonce_str>' . $nonce . '</nonce_str>';
        $param .= '<notify_url>' . $this->notify_url . '</notify_url>';
        $param .= '<out_trade_no>' . $orderno . '</out_trade_no>';
        $param .= '<spbill_create_ip>' . $userIp . '</spbill_create_ip>';
        $param .= '<total_fee>' . $amount . '</total_fee>';
        $param .= '<trade_type>JSAPI</trade_type>';
        $param .= '<openid>' . $openid . '</openid>';
        $param .= '<sign_type>MD5</sign_type>';
        $param .= '<sign>' . $signStr . '</sign>';
        $param .= '</xml>';
        $this->db->wxPayModify($logid, ['to_req'=>$param]);
        $httpUrl = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $res = $this->toCurl($httpUrl, $param);
        $payData = [
            'to_back' => json_encode($res, JSON_UNESCAPED_UNICODE),
        ];
        $this->db->wxPayModify($logid, $payData); //支付log
        if ($res['code'] < 0) {
            return $this->toJson(-2, $res['msg']);
        }
        //用于唤起的参数
        $resData = [
            'appId' => $this->app_id,
            'timeStamp' => (string) time(),
            'nonceStr' => $nonce,
            'package' => 'prepay_id=' . $res['data']['prepay_id'],
            'signType' => 'MD5',
            'total_fee' => $amount,
        ];
        ksort($resData);
        $string = '';
        foreach ($resData as $k => $v) {
            if ($v) {
                $string .= $k . '=' . $v . '&';
            }
        }
        $string .= 'key=' . $this->key;
        $resData['mchId'] = $this->mch_id;
        $resData['orderInfo'] = $type_name;
        $resData['key'] = $this->key;
        $resData['paySign'] = strtoupper(md5($string));
        $payData = [
            'pay_info' => json_encode($resData, JSON_UNESCAPED_UNICODE),
            'status' => 1,
        ];
        $this->db->wxPayModify($logid, $payData); //支付log
        return $this->toJson(0, '', $resData);
    }

    /**
     * 构建CURL请求，单线程
     * @param string $httpUrl 请求地址
     * @param string $string 参数拼接的字符串
     * @return $json
     */
    public function toCurl($httpUrl = '', $string = '', $is_pem = 0)
    {
        $curl = curl_init(); //初始化
        curl_setopt($curl,CURLOPT_URL,$httpUrl);
        curl_setopt($curl, CURLOPT_HEADER, 0);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($curl, CURLOPT_FORBID_REUSE, 1);
        curl_setopt($curl, CURLOPT_FRESH_CONNECT, 1);
        curl_setopt($curl, CURLOPT_ENCODING, '');
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $string);
        curl_setopt($curl, CURLOPT_HTTPHEADER, array(
            'Content-Type: application/json', 'Content-Length: ' . strlen($string)
        ));
        if ($is_pem) {
            curl_setopt($curl, CURLOPT_SSLCERTTYPE, 'PEM');
            curl_setopt($curl, CURLOPT_SSLCERT, '/www/tiepi/public/apiclient_cert.pem');
            curl_setopt($curl, CURLOPT_SSLKEYTYPE, 'PEM');
            curl_setopt($curl, CURLOPT_SSLKEY, '/www/tiepi/public/apiclient_key.pem');
        }
        curl_setopt($curl, CURLOPT_TIMEOUT, 5);
        $output = curl_exec($curl);
        curl_close($curl);
        //ddd($output);
        if (!$output) {
            return array('code'=>-1, 'msg'=>'请求失败');
        }
        if ($is_pem) {
            $items = $this->xml2arr2($output);
        } else {
            $items = $this->xml2arr($output);
        }
        if ($items['code'] < 0) {
            return array('code' => -2,'msg' => 'XML解析错误', 'data' => $items);
        }
        return array('code' => 0,'msg' => 'success', 'data' => $items['data']);
    }

    //解析xml
    public function xml2arr($xml)
    {
        $items = [];
        ////////////////////////正则匹配
        $prefix = '<![CDATA['; $suffix = ']]>';
        //return_code
        $res = preg_match('/<return_code>(.*?)<\/return_code>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'return_code 缺失', 'data' => $xml);
        }
        $return_code = $matches[1];
        if (substr($return_code, 0, strlen($prefix)) == $prefix) {
            $return_code = substr($return_code, 9);
        }
        if (substr($return_code, -3) == $suffix) {
            $return_code = substr($return_code, 0, -3);
        }
        $items['return_code'] = $return_code;
        //result_code
        $res = preg_match('/<result_code>(.*?)<\/result_code>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'result_code 缺失', 'data' => $xml);
        }
        $result_code = $matches[1];
        if (substr($result_code, 0, strlen($prefix)) == $prefix) {
            $result_code = substr($result_code, 9);
        }
        if (substr($result_code, -3) == $suffix) {
            $result_code = substr($result_code, 0, -3);
        }
        $items['result_code'] = $result_code;
        //prepay_id
        $res = preg_match('/<prepay_id>(.*?)<\/prepay_id>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'prepay_id 缺失', 'data' => $xml);
        }
        $prepay_id = $matches[1];
        if (substr($prepay_id, 0, strlen($prefix)) == $prefix) {
            $prepay_id = substr($prepay_id, 9);
        }
        if (substr($prepay_id, -3) == $suffix) {
            $prepay_id = substr($prepay_id, 0, -3);
        }
        $items['prepay_id'] = $prepay_id;
        //return_msg
        $res = preg_match('/<return_msg>(.*?)<\/return_msg>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'prepay_id 缺失', 'data' => $xml);
        }
        $return_msg = $matches[1];
        if (substr($return_msg, 0, strlen($prefix)) == $prefix) {
            $return_msg = substr($return_msg, 9);
        }
        if (substr($return_msg, -3) == $suffix) {
            $return_msg = substr($return_msg, 0, -3);
        }
        $items['return_msg'] = $return_msg;
        //判断错误
        if ($return_code != 'SUCCESS' || $result_code != 'SUCCESS') {
            return array('code' => -2, 'msg' => $return_msg, 'data' => $xml);
        }
        return array('code' => 0, 'msg' => 'success', 'data' => $items);
    }

    //解析xml退款
    public function xml2arr2($xml)
    {
        $items = [];
        ////////////////////////正则匹配
        $prefix = '<![CDATA['; $suffix = ']]>';
        //return_code
        $res = preg_match('/<return_code>(.*?)<\/return_code>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'return_code 缺失', 'data' => $xml);
        }
        $return_code = $matches[1];
        if (substr($return_code, 0, strlen($prefix)) == $prefix) {
            $return_code = substr($return_code, 9);
        }
        if (substr($return_code, -3) == $suffix) {
            $return_code = substr($return_code, 0, -3);
        }
        $items['return_code'] = $return_code;
        //result_code
        $res = preg_match('/<result_code>(.*?)<\/result_code>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'result_code 缺失', 'data' => $xml);
        }
        $result_code = $matches[1];
        if (substr($result_code, 0, strlen($prefix)) == $prefix) {
            $result_code = substr($result_code, 9);
        }
        if (substr($result_code, -3) == $suffix) {
            $result_code = substr($result_code, 0, -3);
        }
        $items['result_code'] = $result_code;
        //return_msg
        $res = preg_match('/<return_msg>(.*?)<\/return_msg>/', $xml, $matches);
        if (!$res) {
            return array('code' => -2, 'msg' => 'prepay_id 缺失', 'data' => $xml);
        }
        $return_msg = $matches[1];
        if (substr($return_msg, 0, strlen($prefix)) == $prefix) {
            $return_msg = substr($return_msg, 9);
        }
        if (substr($return_msg, -3) == $suffix) {
            $return_msg = substr($return_msg, 0, -3);
        }
        $items['return_msg'] = $return_msg;
        //判断错误
        if ($return_code != 'SUCCESS' || $result_code != 'SUCCESS') {
            return array('code' => -2, 'msg' => $return_msg, 'data' => $xml);
        }
        return array('code' => 0, 'msg' => 'success', 'data' => $items);
    }

    //微信通知
    public function notice()
    {
        $xml = file_get_contents('php://input');
        $lastid = $this->db->wxNotice(json_decode($xml, true),1);
        $prefix = '<![CDATA['; $suffix = ']]>';
        //return_code
        $res = preg_match('/<return_code>(.*?)<\/return_code>/', $xml, $matches);
        if (!$res) {
            return $this->toJson(-2, 'return_code 缺失');
        }
        $return_code = $matches[1];
        if (substr($return_code, 0, strlen($prefix)) == $prefix) {
            $return_code = substr($return_code, 9);
        }
        if (substr($return_code, -3) == $suffix) {
            $return_code = substr($return_code, 0, -3);
        }
        if ($return_code != 'SUCCESS') {
            return $this->toJson(-2, '通信失败');
        }
        $items['return_code'] = $return_code;
        //result_code
        $res = preg_match('/<result_code>(.*?)<\/result_code>/', $xml, $matches);
        if (!$res) {
            return $this->toJson(-2, 'result_code 缺失');
        }
        $result_code = $matches[1];
        if (substr($result_code, 0, strlen($prefix)) == $prefix) {
            $result_code = substr($result_code, 9);
        }
        if (substr($result_code, -3) == $suffix) {
            $result_code = substr($result_code, 0, -3);
        }
        if ($result_code != 'SUCCESS') {
            return $this->toJson(-2, '交易失败');
        }
        $items['result_code'] = $return_code;
        //out_trade_no
        $res = preg_match('/<out_trade_no>(.*?)<\/out_trade_no>/', $xml, $matches);
        if (!$res) {
            return $this->toJson(-2, 'out_trade_no 缺失');
        }
        $out_trade_no = $matches[1];
        if (substr($out_trade_no, 0, strlen($prefix)) == $prefix) {
            $out_trade_no = substr($out_trade_no, 9);
        }
        if (substr($out_trade_no, -3) == $suffix) {
            $out_trade_no = substr($out_trade_no, 0, -3);
        }
        $this->db->wxNoticeModify($lastid, $out_trade_no);
        return $this->toJson(0, '', $items);
    }
}
